package org.stone.project.common.config;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.stone.project.common.pojo.annotation.MarkEnum;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Collectors;

@Aspect
@Configuration
@ConditionalOnProperty(name = "cus-scan.enable",havingValue = "true", matchIfMissing = false)
public class CusPackageScan {
    @Value(value = "#{'${cus-scan.package-list}'.split(',')}")
    private List<String> packageList;

    /**
     * 扫描系统枚举类值
     * @return
     */
    @Bean("enumMap")
    public Map<String,List<Map<String,Object>>> scanEnumInfo() throws ClassNotFoundException {
        Map<String,List<Map<String,Object>>> enumMap = new HashMap<>();
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
        scanner.addIncludeFilter(new AnnotationTypeFilter(MarkEnum.class));
        for (String packageName : packageList) {
            Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(packageName);// 替换为你的包名
            for (BeanDefinition bean : candidateComponents) {
                String className = bean.getBeanClassName();
                Class<?> markEnum = Class.forName(className);
                if (markEnum.isEnum()){
                    Annotation[] annotations = markEnum.getAnnotations();
                    String name = null;
                    for (Annotation annotation : annotations) {
                        if (annotation instanceof MarkEnum){
                            name = ((MarkEnum) annotation).value();
                        }
                    }
                    if(ObjectUtil.isEmpty(name)){
                        throw new RuntimeException("枚举扫描信息不能为空");
                    }

                    List<Map<String, Object>> enumList = new ArrayList<>();
                    //枚举类型遍历
                    Field[] fieldsTmp = ReflectUtil.getFieldsDirectly(markEnum,false);
                    List<Field> fields = Arrays.asList(fieldsTmp).stream()
                            .filter(ele -> {
                                return !ele.getName().equals("$VALUES");
                            })
                            .filter(ele->{
                                return !Modifier.isStatic(ele.getModifiers());
                            })
                            .collect(Collectors.toList());
                    //获取具体枚举
                    Object[] enums = markEnum.getEnumConstants();
                    for (Object anEnum : enums) {
                        Map<String, Object> enumMapSon  = new LinkedHashMap<>();
                        for (Field field : fields) {
                            Object fieldValue = ReflectUtil.getFieldValue(anEnum, field);
                            enumMapSon.put(field.getName(),fieldValue);
                        }
                        enumList.add(enumMapSon);
                    }
                    List<Map<String, Object>> has = enumMap.put(name, enumList);
                    if (ObjectUtil.isNotNull(has)){
                        throw new RuntimeException(name+"枚举已注册");
                    }
                }else {
                    throw new RuntimeException("标记类名"+className+"非枚举");
                }
            }
        }
        return enumMap;
    }
}
